package com.cscj.android.repository.repo.shortcut

import androidx.room.withTransaction
import com.cscj.android.repository.db.CacheDatabase
import com.cscj.android.repository.db.dao.ShortCutDao
import com.cscj.android.repository.db.entity.ShortCutCategoryEntity
import com.cscj.android.repository.db.entity.ShortCutEntity
import com.cscj.android.repository.db.entity.ShortCutEntryEntity
import com.cscj.android.repository.network.Result
import com.cscj.android.repository.network.ResultFlowTransformer
import com.cscj.android.repository.network.api.service.ShortCutService
import com.cscj.android.repository.uidata.ShortCutUIData
import kotlinx.coroutines.flow.Flow
import org.koin.core.component.KoinComponent
import org.koin.core.component.inject

class ShortCutRepositoryImpl : ShortCutRepository, KoinComponent {

    private val shortCutDao by inject<ShortCutDao>()

    private val database by inject<CacheDatabase>()

    private val shortCutService by inject<ShortCutService>()

    private val transformer by inject<ResultFlowTransformer>()


    override suspend fun addLinkShortCut(shortCutId: Int): Result<Unit> {
        return transformer.asResult(networkCall = {
            shortCutService.addShortCut(shortCutId, ShortCutEntryEntity.EntryTypeShortCut)
        }, successCall = {
            database.withTransaction {
                val maxOrder = shortCutDao.getMaxShortCutEntrySortOrder()
                val entity = it.data.let { data ->
                    ShortCutEntryEntity(
                        id = data.id,
                        type = data.type,
                        icon = data.icon,
                        name = data.getFixedName(),
                        link = data.link,
                        sortOrder = maxOrder + 1,
                        isRoot = data.isRoot()
                    )
                }
                shortCutDao.upsertShortCutEntry(entity)
                shortCutDao.markShortCutAdded(shortCutId)
            }

        }, transformer = {})
    }

    override suspend fun addHistoryShortCut(
        name: String?, link: String?, icon: String?, isRoot: Boolean
    ): Result<Unit> {
        return transformer.asResult(networkCall = {
            if(isRoot){
                shortCutService.addRootShortCut(ShortCutEntryEntity.EntryTypeHistory)
            } else{
                shortCutService.addHistoryShortCut(name, link, icon)
            }

        }, successCall = {
            database.withTransaction {
                val maxOrder = shortCutDao.getMaxShortCutEntrySortOrder()
                val entity = it.data.let { data ->
                    ShortCutEntryEntity(
                        id = data.id,
                        type = ShortCutEntryEntity.EntryTypeHistory,
                        icon = data.icon,
                        name = data.getFixedName(),
                        link = link,
                        sortOrder = maxOrder + 1,
                        isRoot = data.isRoot()
                    )
                }
                shortCutDao.upsertShortCutEntry(entity)
            }

        }, transformer = {})
    }

    override suspend fun addFavoriteShortCut(
        name: String?,
        link: String?,
        icon: String?,
        isRoot: Boolean
    ): Result<Unit> {
        return transformer.asResult(networkCall = {
            if(isRoot){
                shortCutService.addRootShortCut(ShortCutEntryEntity.EntryTypeFavorites)
            }else{
                shortCutService.addFavoriteShortCut(name, link, icon)
            }

        }, successCall = {
            database.withTransaction {
                val maxOrder = shortCutDao.getMaxShortCutEntrySortOrder()
                val entity = it.data.let { data ->
                    ShortCutEntryEntity(
                        id = data.id,
                        type = ShortCutEntryEntity.EntryTypeFavorites,
                        icon = data.icon,
                        name = data.getFixedName(),
                        link = data.link,
                        sortOrder = maxOrder + 1,
                        isRoot = data.isRoot()
                    )
                }
                shortCutDao.upsertShortCutEntry(entity)
            }

        }, transformer = {})
    }

    override suspend fun deleteShortCutEntry(shortCutId: Int): Result<Unit> {
        return transformer.asResult(networkCall = {
            shortCutService.deleteShortCut(shortCutId)
        }, successCall = {
            shortCutDao.deleteShortCutEntry(shortCutId)
        }, transformer = {})
    }

    override fun loadShortCuts(): Flow<Result<List<ShortCutUIData>>> {
        return transformer.asBoundedResultFlow(cacheFlow = { shortCutDao.shortCutListFlow() },
            networkCall = {
                shortCutService.loadAllShortCuts()
            },
            successCall = {
                database.withTransaction {
                    val categoryList = it.data.mapIndexed { index, category ->
                        ShortCutCategoryEntity(
                            id = category.id, name = category.name, sortOrder = index
                        )
                    }

                    val shortCutList = it.data.flatMap { category ->
                        category.shortCutList
                    }.map { sc ->
                        ShortCutEntity(
                            id = sc.id,
                            categoryId = sc.categoryId,
                            icon = sc.icon,
                            link = sc.link,
                            name = sc.name,
                            added = sc.added > 0,
                            sortOrder = sc.sortOrder,
                        )
                    }

                    shortCutDao.upsertCategories(categoryList)
                    shortCutDao.upsertShortCuts(shortCutList)
                }

            })
    }

    override suspend fun loadShortCutEntries(): Result<Unit> {
        return transformer.asResult(networkCall = {
            shortCutService.loadAllShortCutEntry()
        }, successCall = {
            database.withTransaction {
                shortCutDao.deleteShortCutEntries()
                shortCutDao.upsertShortCutEntries(it.data.mapIndexed { index, shortCutEntry ->
                    ShortCutEntryEntity(
                        id = shortCutEntry.id,
                        type = shortCutEntry.type,
                        icon = shortCutEntry.icon,
                        name = shortCutEntry.getFixedName(),
                        link = shortCutEntry.link,
                        sortOrder = index,
                        isRoot = shortCutEntry.isRoot()
                    )
                })
            }

        }, transformer = {})
    }

    override fun localShortCutEntriesFlow(): Flow<List<ShortCutEntryEntity>> {
        return shortCutDao.shortCutEntriesFlow()
    }

    override suspend fun isItemAdded(type: Int, url: String?): Boolean {
        return if (url.isNullOrBlank()) {
            shortCutDao.getRootEntryCount(type) > 0
        } else {
            shortCutDao.getEntryCount(type, url) > 0
        }
    }
}